home *** CD-ROM | disk | FTP | other *** search
/ APDL Eductation Resources / APDL Eductation Resources.iso / programs / astronomy / skyview / !SkyView / c / Moon < prev    next >
Encoding:
Text File  |  1993-08-26  |  22.1 KB  |  633 lines

  1. /********************************************************/
  2. /*               Moon Module for SkyView                */
  3. /*                                                      */
  4. /*                  (c)1992 N P Hawkes                  */
  5. /*                                                      */
  6. /*                  Displays the Moon.                  */
  7. /********************************************************/
  8.  
  9. #include "menu.h"
  10. #include "dbox.h"
  11. #include "bbc.h"
  12. #include "wimpt.h"
  13. #include "dbox.h"
  14. #include "string.h"
  15. #include "sprite.h"
  16. #include "res.h"
  17. #include "resspr.h"
  18.  
  19. #include "sv_header.h"
  20. #include "datime.h"
  21. #include "radec.h"
  22. #include "ecliptic.h"
  23. #include "riset.h"
  24. #include "moon.h"
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <math.h>
  29.  
  30. /********************************************************/
  31. /*                     Constants                        */
  32. /********************************************************/
  33. #define DISP_NAME "The Moon" /* Entry in Display menu.  */
  34. #define SEL_NAME  "The Moon" /* Entry in Select menu.   */
  35.  
  36. /*  Set effective altitude of horizon for calculations  */
  37. /* of rising and setting.                               */
  38. #define HORALT (REAL)0.0088
  39.  
  40. #define CONVERGE    5       /* Convergence criterion in */
  41.                             /* phenomenon calculations. */
  42. #define MAX_ITER    5       /* Max no. of iterations.   */
  43.  
  44. #define NUM_SPR     4       /* Number of different Moon */
  45.                             /* symbols (for diff. ages).*/
  46. #define SPRNAM_MAX 13       /* Max len of spr name, +1. */
  47.  
  48. /********************************************************/
  49. /*                  Global Variables                    */
  50. /********************************************************/
  51. static BOOL display_flag = TRUE;   /* 'Enabled' flag.   */
  52. static int moduleid;    /* Module ID.                   */
  53. static int horiz_id;    /* Moon's ID in Horiz window.   */
  54. static int vert_id;     /* Moon's ID in Vert window.    */
  55. static REAL moonra;     /* Right Ascension of Moon.     */
  56. static REAL moondec;    /* Declination of Moon.         */
  57. static REAL moonage;    /* Age of Moon.                 */
  58. static int  moon_symbol;/* Which Moon sprite to use.    */
  59.  
  60. /* Array of (address-type) sprite_ids for Moon symbols: */
  61. static sprite_id moon_spr[NUM_SPR];
  62.  
  63. /********************************************************/
  64. /*                 Function Prototypes                  */
  65. /********************************************************/
  66. static BOOL make_sprite_id(char *namestr, int i, sprite_id *idptr);
  67. static BOOL make_sprite_name(char *namestr, int i, char *spr_name);
  68. static void moon_buildfn(void);
  69. static void moon_altaz(REAL *altptr, REAL *azimptr);
  70. static void age(REAL *ageptr, int *symbolptr);
  71. static void moon_altaz_any(observerstr *ptr, int hour, int min,
  72.                           REAL *altptr, REAL *azimptr);
  73. static void moon_radecfn(int id, observerstr *ob_ptr, int hour, int min,
  74.                           REAL *traptr, REAL *tdecptr);
  75. static void geocentric_rradec(double jul,
  76.                           REAL *rptr, REAL *raptr, REAL *decptr);
  77. static void topocentric_radec(observerstr *ob_ptr, REAL sid,
  78.                           REAL r, REAL ra, REAL dec,
  79.                           REAL *traptr, REAL *tdecptr);
  80. static void geocentric_elatlong(double jul,
  81.                                 REAL *elatptr, REAL *elongptr, double *pptr);
  82. static void moon_selectfn(selectfn_reasoncode reason);
  83. static void selection_details(void);
  84. static BOOL cul_calc(REAL altmin,
  85.                 REAL *altptr, REAL *azimptr, int *hourptr, int *minptr);
  86. static BOOL rs_calc(BOOL whichcalc,
  87.                     REAL *altptr, REAL *azimptr, int *hourptr, int *minptr);
  88. static BOOL moon_displayfn(BOOL *enabptr);
  89. static os_error *moon_plotfn(int x, int y, int id);
  90. static void moon_infofn(int id);
  91.  
  92. /********************************************************/
  93. /*                Initialisation Function               */
  94. /********************************************************/
  95. BOOL moon_initfn(int moduleno, modulestr *moon)
  96. {
  97.   int i;
  98.  
  99.   moduleid = moduleno;
  100.  
  101.   moon->buildfn  = moon_buildfn;
  102.   moon->selectfn = moon_selectfn;
  103.   moon->dispfn   = moon_displayfn;
  104.   moon->infofn   = moon_infofn;
  105.   moon->initial  = display_flag;
  106.   moon->display_entry = DISP_NAME;
  107.   moon->display_menu  = NULL;
  108.   moon->select_entry  = SEL_NAME;
  109.   moon->select_menu   = NULL;
  110.  
  111. /* Construct an array of address-type sprite_ids, each  */
  112. /* for a different age of the Moon.  Quit if error.     */
  113.   for (i = 0; i < NUM_SPR; i++)
  114.     if (!make_sprite_id("moon", i, moon_spr + i)) return FALSE;
  115.  
  116.   return TRUE;
  117. }
  118.  
  119. /*------------------------------------------------------*/
  120. /*   Function to build an address-type sprite id corr-  */
  121. /* esponding to the sprite name returned by the function*/
  122. /* make_sprite_name. Returns TRUE if no errors detected.*/
  123. /*------------------------------------------------------*/
  124. static BOOL make_sprite_id(char *namestr, int i, sprite_id *idptr)
  125. {
  126.   char spr_name[SPRNAM_MAX]; /*For built-up sprite name.*/
  127.   sprite_id nametype_id;
  128.  
  129. /* Construct sprite name.                               */
  130.   if (!make_sprite_name(namestr, i, spr_name)) return FALSE;
  131.  
  132. /* Form a name-type sprite id using this name.          */
  133.   nametype_id.s.name = spr_name;
  134.   nametype_id.tag    = sprite_id_name;
  135.  
  136. /* Get address of sprite.  Quit if error.               */
  137.   if (sprite_select_rp(resspr_area(),
  138.                        &nametype_id,
  139.                        &idptr->s.addr) != NULL) return FALSE;
  140.  
  141. /* Set tag to identify *idptr as an address-type id.    */
  142.   idptr->tag = sprite_id_addr;
  143.  
  144.   return TRUE;
  145. }
  146.  
  147. /*------------------------------------------------------*/
  148. /* Function to make a sprite name from the given string */
  149. /* namestr and the given integer i.  The name made is of*/
  150. /* the form ssssnnn, where ssss is the first 9 chars of */
  151. /* the given string (fewer if the string is shorter) and*/
  152. /* nnn is the integer i expressed as 3 digits (000-999).*/
  153. /* String pointed to by spr_name is assumed long enough.*/
  154. /*          Return FALSE if error detected.             */
  155. /*------------------------------------------------------*/
  156. static BOOL make_sprite_name(char *namestr, int i, char *spr_name)
  157. {
  158.   int len;
  159.  
  160.   if (i<0 || i>999) return FALSE;
  161.  
  162. /* Copy at most 9 chars from namestr to spr_name.       */
  163.   strncpy(spr_name, namestr, 9);
  164.  
  165. /* Add number.                                          */
  166.   len = strlen(namestr);
  167.   if (len > 9) len = 9;
  168.   sprintf(spr_name+len, "%03i", i);
  169.  
  170.   return TRUE;
  171. }
  172.  
  173.  
  174. /********************************************************/
  175. /*                 List-Building Function               */
  176. /********************************************************/
  177. static void moon_buildfn(void)
  178. {
  179.   plotobj the_moon;
  180.   /* Bounding box of plotting symbol, relative to       */
  181.   /* position of symbol:                                */
  182.   wimp_box size = {-12, -12, 14, 14};
  183.  
  184. /* Choose to rebuild list regardless of whether or not  */
  185. /* this module is enabled.                              */
  186.  
  187. /* Set up the one and only object owned by this module. */
  188.   the_moon.id = 0;
  189.   the_moon.module = moduleid;
  190.   the_moon.plotfn = moon_plotfn;
  191.   moon_altaz(&the_moon.alt, &the_moon.azim);
  192.   the_moon.size = size;
  193.  
  194. /* Add this object to the plotting lists.               */
  195.   addobj(the_moon, &horiz_id, &vert_id);
  196.  
  197. /* Also calculate age, and which moon symbol to use.    */
  198.   age(&moonage, &moon_symbol);
  199.  
  200.   return;
  201. }
  202.  
  203. /*------------------------------------------------------*/
  204. /* Function to calculate the Moon's current alt & azim. */
  205. /*------------------------------------------------------*/
  206. static void moon_altaz(REAL *altptr, REAL *azimptr)
  207. {
  208.   REAL r;           /* Moon-Earth dist (in Earth radii).*/
  209.   REAL ra, dec;     /* Geocentric RA and Dec of Moon.   */
  210.  
  211. /* Get the current geocentric RA and Dec of the Moon,   */
  212. /* and its distance from the Earth.                     */
  213.   geocentric_rradec(ob_data.jul, &r, &ra, &dec);
  214.  
  215. /* Convert to topocentric RA and Dec.                   */
  216.   topocentric_radec(&ob_data, ob_data.sid, r, ra, dec, &moonra, &moondec);
  217.  
  218. /* Convert to altitude and azimuth.                     */
  219.   radec_altaz(moonra, moondec, &ob_data, ob_data.sid, altptr, azimptr);
  220.  
  221.   return;
  222. }
  223.  
  224. /*------------------------------------------------------*/
  225. /*   Function to calculate Moon's alt & azim at any     */
  226. /*    hour & min of the day specified in the given      */
  227. /*   observerstr (which also specifies the location).   */
  228. /*------------------------------------------------------*/
  229. static void moon_altaz_any(observerstr *ptr, int hour, int min,
  230.                           REAL *altptr, REAL *azimptr)
  231. {
  232.   REAL r;         /* Moon-Earth dist (in Earth radii).  */
  233.   REAL ra, dec;   /* Geocentric RA and Dec of Moon.     */
  234.   REAL tra, tdec; /* Topocentric RA and Dec of Moon.    */
  235.   double jul;     /* Days since noon GMT 0/1/1900.      */
  236.   REAL sid;       /* Local siderial time.               */
  237.  
  238.   jul = datime_julian(ptr, hour, min);
  239.   sid = datime_siderial(ptr, jul, hour, min);
  240.  
  241. /* Get dist & geocentric RA and Dec.                    */
  242.   geocentric_rradec(jul, &r, &ra, &dec);
  243.  
  244. /* Convert to topocentric RA and Dec.                   */
  245.   topocentric_radec(ptr, sid, r, ra, dec, &tra, &tdec);
  246.  
  247. /* Convert to altitude and azimuth.                     */
  248.   radec_altaz(tra, tdec, ptr, sid, altptr, azimptr);
  249.  
  250.   return;
  251. }
  252.  
  253. /*------------------------------------------------------*/
  254. /*   Function to calculate the topocentric RA & Dec of  */
  255. /*  the Moon at a specified instant.  The parameters of */
  256. /*   this function conform to the requirements of the   */
  257. /*                  'Riset' functions.                  */
  258. /*------------------------------------------------------*/
  259. static void moon_radecfn(int id, observerstr *ob_ptr, int hour, int min,
  260.                          REAL *traptr, REAL *tdecptr)
  261. {
  262. /* 'id' is not used as there is only one Moon.          */
  263.  
  264.   REAL r;         /* Moon-Earth dist (in Earth radii).  */
  265.   REAL ra, dec;   /* Geocentric RA and Dec of Moon.     */
  266.   double jul;     /* Days since noon GMT 0/1/1900.      */
  267.   REAL sid;       /* Local siderial time.               */
  268.  
  269.   jul = datime_julian(ob_ptr, hour, min);
  270.   sid = datime_siderial(ob_ptr, jul, hour, min);
  271.  
  272. /* Get dist & geocentric RA and Dec.                    */
  273.   geocentric_rradec(jul, &r, &ra, &dec);
  274.  
  275. /* Convert to topocentric RA and Dec.                   */
  276.   topocentric_radec(ob_ptr, sid, r, ra, dec, traptr, tdecptr);
  277.  
  278.   return;
  279. }
  280.  
  281. /*------------------------------------------------------*/
  282. /*  Function to calculate the geocentric RA and Dec of  */
  283. /* the Moon, and its dist from Earth (in Earth radii).  */
  284. /*------------------------------------------------------*/
  285. static void geocentric_rradec(double jul,
  286.                               REAL *rptr, REAL *raptr, REAL *decptr)
  287. {
  288.   double T;     /* Centuries since noon GMT 0/1/1900.   */
  289.   double p;     /* Horizontal parallax.                 */
  290.   double r;     /* Distance from Earth.                 */
  291.   REAL elatit;  /* Geocentric ecliptic latitude.        */
  292.   REAL elongit; /* Geocentric ecliptic longitude.       */
  293.  
  294. /* Get geocent. eclipt. lat & long, and horiz. parallax.*/
  295.   geocentric_elatlong(jul, &elatit, &elongit, &p);
  296.  
  297. /* Convert to geocentric RA and Dec.                    */
  298.   T = jul/36525.0;
  299.   ecliptic_radec(elatit, elongit, T, raptr, decptr);
  300.  
  301. /* Calculate distance from Earth.                       */
  302.   r = 1.0 / sin(p);
  303.   *rptr = (REAL)r;
  304.  
  305.   return;
  306. }
  307.  
  308. /*------------------------------------------------------*/
  309. /*    Function to calculate the geocentric ecliptic     */
  310. /*     latitude and longitude of the Moon, and the      */
  311. /*  horizontal parallax, at the instant implied by jul  */
  312. /* (No. of days since noon GMT on 0/1/1900).  Based on  */
  313. /*   algorithm in NAO Technical Note No.46, Jan 1978,   */
  314. /*            page 28.  Angles in radians.              */
  315. /*------------------------------------------------------*/
  316. static void geocentric_elatlong(double jul,
  317.                                 REAL *elatptr, REAL *elongptr, double *pptr)
  318. {
  319.   double M1, L, M, N, F, tN;
  320.   double beta, lambda;
  321.  
  322.   M1 = DblCONV*fmod(358.48 +  0.985600*jul, 360.0);
  323.   L  =         fmod(270.43 + 13.176397*jul, 360.0);
  324.   M  = DblCONV*fmod(296.10 + 13.064992*jul, 360.0);
  325.   N  = DblCONV*fmod(350.74 + 12.190749*jul, 360.0);
  326.   F  = DblCONV*fmod( 11.25 + 13.229350*jul, 360.0);
  327.  
  328.   tN = 2.0*N;
  329.  
  330. /* Geocentric ecliptic latitude:                        */
  331.   beta =  5.128 * sin(F)
  332.         + 0.281 * sin(M  + F)
  333.         + 0.278 * sin(M  - F)
  334.         + 0.173 * sin(tN - F)
  335.         - 0.055 * sin(M  - tN - F)
  336.         - 0.046 * sin(M  - tN + F)
  337.         + 0.033 * sin(tN + F);
  338.   if (beta <    0.0) beta += 360.0;
  339.   if (beta >= 360.0) beta  =   0.0;
  340.   *elatptr = CONV * (REAL)beta;
  341.  
  342. /* Geocentric ecliptic longitude:                       */
  343.   lambda =   L
  344.            + 6.289 * sin(M)
  345.            - 1.274 * sin(M  - tN)
  346.            + 0.658 * sin(tN)
  347.            + 0.214 * sin(2.0*M)
  348.            - 0.186 * sin(M1)
  349.            - 0.114 * sin(2.0*F)
  350.            - 0.059 * sin(2.0*M  - tN)
  351.            - 0.057 * sin(M1 + M - tN)
  352.            + 0.053 * sin(M  + tN)
  353.            - 0.046 * sin(M1 - tN)
  354.            + 0.041 * sin(M  - M1)
  355.            - 0.035 * sin(N)
  356.            - 0.030 * sin(M  + M1);
  357.   if (lambda <    0.0) lambda += 360.0;
  358.   if (lambda >= 360.0) lambda -= 360.0;
  359.   if (lambda <    0.0) lambda  =   0.0;
  360.   *elongptr = CONV * (REAL)lambda;
  361.  
  362. /* Parallax:                                            */
  363.   *pptr =   0.9507
  364.           + 0.0518 * cos(M)
  365.           + 0.0095 * cos(M - tN)
  366.           + 0.0078 * cos(tN)
  367.           + 0.0028 * cos(2.0*M);
  368.   *pptr *= DblCONV;
  369.  
  370.   return;
  371. }
  372.  
  373. /*------------------------------------------------------*/
  374. /*     Function to convert geocentric RA and Dec to     */
  375. /*    (approx) topocentric RA and Dec.  Formula from    */
  376. /*          Astronomical Almanac 1990, p. D46.          */
  377. /*------------------------------------------------------*/
  378. static void topocentric_radec(observerstr *ob_ptr, REAL sid,
  379.                               REAL r, REAL ra, REAL dec,
  380.                               REAL *traptr, REAL *tdecptr)
  381. {
  382.   double x,  y,  z;  /* Geocentric rectangular coords.  */
  383.   double x1, y1, z1; /* Topocentric rectangular coords. */
  384.   double r1;
  385.   double tra, tdec;
  386.   double sintdec;
  387.  
  388. /* Get geocentric rectangular coords.                   */
  389.   x = (double)r * cos((double)dec) * cos((double)ra);
  390.   y = (double)r * cos((double)dec) * sin((double)ra);
  391.   z = (double)r * sin((double)dec);
  392.  
  393. /* Derive topocentric rectangular coords.               */
  394.   x1 = x - cos((double)ob_ptr->latit) * cos((double)sid);
  395.   y1 = y - cos((double)ob_ptr->latit) * sin((double)sid);
  396.   z1 = z - sin((double)ob_ptr->latit);
  397.   r1 = sqrt(x1*x1 + y1*y1 + z1*z1);
  398.  
  399. /* Derive topocentric RA.                               */
  400.   if (fabs(x1) < 1.0E-7  &&  fabs(y1) < 1.0E-7)
  401.     tra = 0.0;
  402.   else
  403.   {
  404.     tra = atan2(y1, x1);
  405.     if (tra <        0.0) tra += DblTWO_PI;
  406.     if (tra >= DblTWO_PI) tra  = 0.0;
  407.   }
  408.   *traptr = (REAL)tra;
  409.  
  410. /* Derive topocentric Dec.                              */
  411.   sintdec = z1 / r1;
  412.   if (sintdec < -1.0) sintdec = -1.0;
  413.   if (sintdec >  1.0) sintdec =  1.0;
  414.   tdec = asin(sintdec);
  415.   *tdecptr = (REAL)tdec;
  416.  
  417.   return;
  418. }
  419.  
  420. /*------------------------------------------------------*/
  421. /*   Function to calculate the approximate age of the   */
  422. /*        Moon, and decide which symbol to use.         */
  423. /*------------------------------------------------------*/
  424. static void age(REAL *ageptr, int *symbolptr)
  425. {
  426.   double T;    /* Centuries since noon GMT on 0/1/1900. */
  427.   double a, b, c;
  428.   double delta;
  429.  
  430.   T = ob_data.jul / 36525.0;
  431.   b = DblCONV * fmod(296.1  + 477198.75 * T, 360.0);
  432.   c = DblCONV * fmod(358.5  +  35999.04 * T, 360.0);
  433.   a = 350.74 + 445267.14*T + 6.3*sin(b) - 1.9*sin(c);
  434.  
  435.   delta = fmod(a, 360.0);
  436.   *ageptr = (REAL)0.082 * (REAL)delta;
  437.  
  438. /* Divide synodic month into NUM_SPR intervals, with    */
  439. /* offset so that same symbol is used for just before & */
  440. /* just after new moon.  Return a number in the range   */
  441. /* 0 (nearest new moon) to NUM_SPR-1.                   */
  442.   delta += 180.0 / (double)NUM_SPR;
  443.   if (delta >= 360.0) delta -= 360.0;
  444.   if (delta <    0.0) delta  =   0.0;
  445.   delta /= 360.0;
  446.   delta *= (double)NUM_SPR;
  447.   *symbolptr = (int)delta;
  448.   if (*symbolptr <        0) *symbolptr = 0;
  449.   if (*symbolptr >= NUM_SPR) *symbolptr = NUM_SPR - 1;
  450.  
  451.   return;
  452. }
  453.  
  454.  
  455. /********************************************************/
  456. /*              Object-Selecting Function               */
  457. /********************************************************/
  458. static void moon_selectfn(selectfn_reasoncode reason)
  459. {
  460.   switch (reason)
  461.   {
  462.     case new_selection:
  463.       /* Only one Moon, so selection always succeeds.   */
  464.       selection.id = 0;
  465.       selection.selected_OK = TRUE;
  466.     case window_selection:
  467.       /* Selection has been made by clicking in a       */
  468.       /* window.                                        */
  469.     case recalculate_data:
  470.       /* Observer details have changed, and plotting    */
  471.       /* lists have been rebuilt.                       */
  472.       /*                                                */
  473.       /* Fill in the details of rising, setting etc.    */
  474.       selection_details();
  475.       break;
  476.  
  477.     case timeonly_recalculate:
  478.       /* As recalculate_data, but only the time of day  */
  479.       /* (and possibly the direction of view - this is  */
  480.       /* is of no interest) have changed.               */
  481.       /* This simplifies the calculation.               */
  482.       selection.horiz_id = horiz_id;
  483.       selection.vert_id  = vert_id;
  484.       /* Decide if it can be seen now.                  */
  485.       selection.now      = selection.horiz_id != NOWHERE || \
  486.                            selection.vert_id  != NOWHERE;
  487.       break;
  488.  
  489.     case sel_info_request:
  490.       /* Write info into text buffer.   Use Info fn.    */
  491.       moon_infofn(0);
  492.       break;
  493.  
  494.     default:
  495.       /* Unknown option.  Do nothing.                   */
  496.       break;
  497.  
  498.     }
  499.  
  500.   return;
  501. }
  502.  
  503. /*------------------------------------------------------*/
  504. /*  Function to fill in the details of rising, setting  */
  505. /*                   and culminating.                   */
  506. /*------------------------------------------------------*/
  507. static void selection_details(void)
  508. {
  509.   REAL rise_alt;  /*Altitude at calculated rising time. */
  510.   REAL set_alt;   /*Altitude at calculated setting time.*/
  511.  
  512.   selection.horiz_id = horiz_id;
  513.   selection.vert_id  = vert_id;
  514.   selection.now      = selection.horiz_id != NOWHERE || \
  515.                        selection.vert_id  != NOWHERE;
  516.  
  517.   selection.culminating = cul_calc(HORALT,
  518.                               &selection.cul_alt,
  519.                               &selection.cul_azim,
  520.                               &selection.cul_hour,
  521.                               &selection.cul_min);
  522.   selection.rising      = rs_calc(RISECALC,
  523.                               &rise_alt,
  524.                               &selection.rise_azim,
  525.                               &selection.rise_hour,
  526.                               &selection.rise_min);
  527.   selection.setting     = rs_calc(SETCALC,
  528.                               &set_alt,
  529.                               &selection.set_azim,
  530.                               &selection.set_hour,
  531.                               &selection.set_min);
  532.   return;
  533. }
  534.  
  535. /*------------------------------------------------------*/
  536. /*      Function to derive details of culmination.      */
  537. /*  If Moon culminates, fn finds alt, azim, hour & min  */
  538. /* and returns TRUE.  Returns FALSE if no culmination.  */
  539. /*------------------------------------------------------*/
  540. static BOOL cul_calc(REAL altmin,
  541.                 REAL *altptr, REAL *azimptr, int *hourptr, int *minptr)
  542. {
  543.   BOOL ok;
  544.  
  545. /* Guess a time of day.  Take midday.                   */
  546.   *hourptr = 12;
  547.   *minptr  =  0;
  548.  
  549. /* Try to improve guessed time.                         */
  550.   ok = riset_cul(
  551.        &ob_data, MAX_ITER, CONVERGE, moon_radecfn, 0, hourptr, minptr);
  552.  
  553. /* Give up if time did not converge.                    */
  554.   if (!ok) return FALSE;
  555.  
  556. /* Check that Moon would be higher than 'altmin'.       */
  557.   moon_altaz_any(&ob_data, *hourptr, *minptr, altptr, azimptr);
  558.   return (*altptr >= altmin);
  559. }
  560.  
  561. /*------------------------------------------------------*/
  562. /*   Function to derive details of rising or setting.   */
  563. /* If phenomenon occurs, fn finds alt, azim, hour & min */
  564. /*      and returns TRUE.  Returns FALSE otherwise.     */
  565. /*------------------------------------------------------*/
  566. static BOOL rs_calc(BOOL whichcalc,
  567.                     REAL *altptr, REAL *azimptr, int *hourptr, int *minptr)
  568. {
  569.   BOOL ok;
  570.  
  571. /* Guess a time of day.  Take midday.                   */
  572.   *hourptr = 12;
  573.   *minptr  =  0;
  574.  
  575. /* Try to improve this guess.                           */
  576.   ok = riset_riset(&ob_data, MAX_ITER, CONVERGE, moon_radecfn, 0,
  577.                    whichcalc, HORALT, hourptr, minptr);
  578.  
  579. /* Give up if time did not converge to a valid value.   */
  580.   if (!ok) return FALSE;
  581.  
  582. /* Check that Moon is indeed visible at this time.       */
  583.   moon_altaz_any(&ob_data, *hourptr, *minptr, altptr, azimptr);
  584.   return (*altptr > ZERO);
  585. }
  586.  
  587.  
  588. /********************************************************/
  589. /*                   Display Function                   */
  590. /********************************************************/
  591. static BOOL moon_displayfn(BOOL *enabptr)
  592. {
  593. /* Toggle Enable/Disable flag.                          */
  594.   display_flag = !display_flag;
  595.  
  596. /* Inform main program of new status.                   */
  597.   *enabptr = display_flag;
  598.  
  599. /* Data in plotting list is always kept up-to-date, so  */
  600. /* no need to check validity or call list-building fn.  */
  601.  
  602. /* Windows will always need updating.                   */
  603.   return TRUE;
  604. }
  605.  
  606.  
  607. /********************************************************/
  608. /*                   Plotting Function                  */
  609. /********************************************************/
  610. static os_error *moon_plotfn(int x, int y, int id)
  611. {
  612.   return sv_plotsprite(&moon_spr[moon_symbol], MODE_20, x, y, 5, 5);
  613. }
  614.  
  615.  
  616. /********************************************************/
  617. /*                     Info Function                    */
  618. /********************************************************/
  619. static void moon_infofn(int id)
  620. {
  621.   char p_text[RADEC_TEXTLEN]; /*Text buff for RA & Dec.*/
  622.  
  623. /* Get RA and Dec in text form.                        */
  624.   radec_text(moonra, moondec, p_text);
  625.  
  626.   sprintf(infoptr, "%s\n\nApprox age %.1f days\n%s",
  627.     "The Moon",
  628.     (double)moonage,
  629.     p_text);
  630.  
  631.   return;
  632. }
  633.